/**
 * pro-form-render -- 内容面板
 * @author SPY
 * @url 语雀:https://www.yuque.com/study365
 */
import React, { memo, useEffect } from 'react';
import { connect } from 'umi';
import classnames from 'classnames';
import _ from 'lodash';
import { useClickAway, useWhyDidYouUpdate } from 'ahooks';
import {
  sortableContainer,
  sortableElement,
  sortableHandle,
} from 'react-sortable-hoc';
import arrayMove from 'array-move';
import { Row, Col } from 'antd';
import ProForm, {
  ProFormText,
  ProFormTextArea,
  ProFormSelect,
  ProFormCheckbox,
  ProFormRadio,
  ProFormSwitch,
  ProFormDigit,
  ProFormDatePicker,
  ProFormDateTimePicker,
  ProFormDateRangePicker,
  ProFormDateTimeRangePicker,
  ProFormTimePicker,
  ProFormRate,
  ProFormSlider,
  ProFormUploadDragger,
  ProFormUploadButton,
  ProFormCaptcha,
} from '@ant-design/pro-form';
import { DeleteOutlined, DragOutlined } from '@ant-design/icons';
import styles from './index.less';

const Components = {
  ProFormText,
  ProFormTextArea,
  ProFormSelect,
  ProFormCheckbox,
  ProFormSwitch,
  ProFormDigit,
  ProFormDatePicker,
  ProFormDateTimePicker,
  ProFormDateRangePicker,
  ProFormDateTimeRangePicker,
  ProFormTimePicker,
  ProFormRate,
  ProFormSlider,
  ProFormUploadDragger,
  ProFormUploadButton,
  ProFormCaptcha,
};

const { Password } = ProFormText; // 密码框
const { Group } = ProFormRadio; // 单选框

// 拖动手柄
const DragHandle = sortableHandle(() => (
  <DragOutlined className={styles.move_icon} />
));

// 拖动容器
const SortableContainer = sortableContainer(({ children }) => {
  return <div>{children}</div>;
});

// 拖动元素
const SortableItem = connect(({ proForm }) => ({ ...proForm }))(
  sortableElement(
    ({
      item,
      key,
      selectedKey,
      itemList,
      formParams,
      handleOperationItem,
      handleDeleteItem,
    }) => {
      const { type, proFormProps = {}, ...restProps } = item;
      const isSelected = item.key === selectedKey; // 组件是否被选中
      let FormComponent = Components[type];
      // 选中组件信息
      const selectedRow = _.filter(itemList, (i) => i.key === selectedKey);

      if (type === 'ProFormPassword') {
        // 密码框
        FormComponent = Password;
      }
      if (type === 'ProFormRadio') {
        // 单选框
        FormComponent = Group;
      }
      return (
        <Col span={24 / formParams.colSpan || 24}>
          <div
            key={key}
            className={classnames({
              [styles.selected_item]: isSelected,
              [styles.not_selected_item]: !isSelected,
            })}
            onClick={() => handleOperationItem({ selectedKey: item.key })}
          >
            <div
              className={classnames({
                [styles.toolbar]: isSelected,
              })}
            >
              <div
                className={classnames({
                  [styles.not_selected_icon_list]: !isSelected,
                  [styles.selected_icon_list]: isSelected,
                })}
              >
                <DeleteOutlined
                  className={styles.delete_icon}
                  onClick={() => handleDeleteItem(item.key)}
                />
                <DragHandle />
              </div>
            </div>
            <FormComponent key={key} {...restProps} {...proFormProps} />
          </div>
        </Col>
      );
    },
  ),
);

const FormContentPanel = (props) => {
  const {
    dragProps,
    itemList,
    selectedKey,
    formParams,
    clickAwayDoms,
    dispatch,
  } = props;

  useClickAway(() => {
    // 目标元素外点击事件,取消选中
    if (selectedKey) handleOperationItem({ selectedKey: null });
  }, [...clickAwayDoms]);

  useEffect(() => {
    if (dispatch) {
      const clickAwayDefault = document.getElementsByClassName('clickAwayName');
      dispatch({
        type: 'proForm/save',
        payload: {
          clickAwayDoms: clickAwayDefault,
        },
      });
    }
  }, []);

  // 选中、取消组件
  const handleOperationItem = (values) => {
    if (dispatch) {
      dispatch({
        type: 'proForm/save',
        payload: values,
      });
    }
  };

  // 删除单一组件
  const handleDeleteItem = (key) => {
    if (dispatch) {
      dispatch({
        type: 'proForm/deleteFormItem',
        payload: { key },
      });
    }
  };

  // 排序
  const onSortEnd = ({ oldIndex, newIndex }) => {
    if (dispatch) {
      dispatch({
        type: 'proForm/save',
        payload: {
          itemList: arrayMove(_.cloneDeep(itemList), oldIndex, newIndex),
        },
      });
    }
  };

  // const [randomNum, setRandomNum] = useState(Math.random());
  // useWhyDidYouUpdate('useWhyDidYouUpdateComponent', { ...props, randomNum });

  // proForm参数
  const { colSpan, ...restFormParams } = formParams;

  return (
    <div {...dragProps} className={styles.content}>
      {Array.isArray(itemList) && itemList.length ? (
        <div className="clickAwayName">
          <SortableContainer onSortEnd={onSortEnd} useDragHandle distance={5}>
            <ProForm {...restFormParams}>
              <Row gutter={24}>
                {itemList.map((item, index) => (
                  <SortableItem
                    key={`item-${item.key}`}
                    index={index}
                    item={item}
                    handleOperationItem={handleOperationItem}
                    handleDeleteItem={handleDeleteItem}
                  />
                ))}
              </Row>
            </ProForm>
          </SortableContainer>
        </div>
      ) : (
        <div className={styles.no_content}>拖拽左侧栏的组件进行添加</div>
      )}
    </div>
  );
};
export default connect(({ proForm }) => ({
  ...proForm,
}))(memo(FormContentPanel));
